package com.androidcat.fuelmore;

import android.app.Application;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;

import com.androidcat.utilities.LogUtil;
import com.androidcat.utilities.persistence.CacheFileManager;

import java.io.File;

/**
 * <p>
 * Base class for any application which need to send crash reports. The final
 * application has to extend this class and at least implement the abstract
 * method by returning a email that reports will be
 * sent to.
 * </p>
 */
public abstract class CrashReportingApplication extends Application implements
		OnSharedPreferenceChangeListener {
	protected static final String LOG_TAG = "ACRA";
	private static final String CRASH_FILE = "crash.txt";
	/**
	 * Bundle key for the text of cancel button in the crash dialog.
	 * 
	 * @see #getCrashResources()
	 */
	public static final String RES_BUTTON_CANCEL = "RES_BUTTON_CANCEL";
	/**
	 * Bundle key for the text of report button in the crash dialog.
	 * 
	 * @see #getCrashResources()
	 */
	public static final String RES_BUTTON_REPORT = "RES_BUTTON_REPORT";
	/**
	 * Bundle key for the text of restart button in the crash dialog. If the
	 * text is not specified, the restart button will not show.
	 * 
	 * @see #getCrashResources()
	 */
	public static final String RES_BUTTON_RESTART = "RES_BUTTON_RESTART";
	/**
	 * Bundle key for the icon in the crash dialog.
	 * 
	 * @see #getCrashResources()
	 */
	public static final String RES_DIALOG_ICON = "RES_DIALOG_ICON";
	/**
	 * Bundle key for the title in the crash dialog.
	 * 
	 * @see #getCrashResources()
	 */
	public static final String RES_DIALOG_TITLE = "RES_DIALOG_TITLE";
	/**
	 * Bundle key for the text in the crash dialog.
	 * 
	 * @see #getCrashResources()
	 */
	public static final String RES_DIALOG_TEXT = "RES_DIALOG_TEXT";

	/**
	 * Bundle key for the subject of the report email.
	 * 
	 * @see #getCrashResources()
	 */
	public static final String RES_EMAIL_SUBJECT = "RES_EMAIL_SUBJECT";
	/**
	 * Bundle key for the body of the report email.
	 * 
	 * @see #getCrashResources()
	 */
	public static final String RES_EMAIL_TEXT = "RES_EMAIL_TEXT";

	/**
	 * The key of the application default SharedPreference where you can put a
	 * 'true' Boolean value to disable ACRA.
	 */
	public static final String PREF_ENABLE_ACRA = "acra.enable";

	@Override
	public void onCreate() {
		super.onCreate();
		try {
			final SharedPreferences prefs = getACRASharedPreferences();
			prefs.registerOnSharedPreferenceChangeListener(this);
			Log.e(LOG_TAG, "acra init");
			// If the application default shared preferences contains true for
			// the
			// key "acra.disable", do not activate ACRA. Also checks the
			// alternative
			// opposite setting "acra.enable" if "acra.disable" is not found.
			boolean enableAcra = true;

			enableAcra = prefs.getBoolean(PREF_ENABLE_ACRA,
					isCrashReportEnableByDefault());
			// Log.i("i", "isCrashReporterEnabled:"+enableAcra);
			if (enableAcra) {
				initAcra();
			} else {
				Log.d(LOG_TAG, "ACRA is disabled for " + this.getPackageName()
						+ ".");
			}
		} catch (final Exception e) {
			LogUtil.logException(this.getClass(), e);
		}

	}

	/**
	 * Activate ACRA.
	 */
	private void initAcra() {
		 Log.d(LOG_TAG, "ACRA is enabled for " + this.getPackageName() + ",intializing...");
		 // Initialise ErrorReporter with all required data
		 final ErrorReporter errorReporter = ErrorReporter.getInstance();
		 errorReporter.setReportUrl(getReportUrl());
		 // Activate the ErrorReporter
		 errorReporter.init(this);
	}

	/**
	 * Implement this method by returning a email that reports will be sent to.
	 * 
	 * @return The Id of your GoogleDoc Form generated by importing ACRA's
	 *         spreadsheet template.
	 */
	public abstract String getReportUrl();

	/**
	 * Override this method to modify strings showed in crash dialog. Return a
	 * Bundle containing :
	 * <ul>
	 * <li>{@link #RES_BUTTON_REPORT}</li>
	 * <li>{@link #RES_BUTTON_CANCEL}</li>
	 * <li>{@link #RES_DIALOG_ICON}</li>
	 * <li>{@link #RES_DIALOG_TITLE}</li>
	 * <li>{@link #RES_DIALOG_TEXT}</li>
	 * <li>{@link #RES_EMAIL_SUBJECT}</li>
	 * <li>{@link #RES_EMAIL_TEXT}</li>
	 * </ul>
	 * 
	 * @return A Bundle containing the resource String necessary to interact
	 *         with the user.
	 */
	public abstract Bundle getCrashResources();

	/**
	 * Override this method to change the location of crash report file. The
	 * file should be on external storage,otherwise the email can't send this
	 * file as attachment.
	 * 
	 * @return
	 */
	public File getCrashReportFile() {
		return new File(CacheFileManager.FILE_EXCEPTION_LOG, CRASH_FILE);
	}

	/**
	 * Called when user click "restart" button of crash dialog.
	 * 
	 * @see #RES_BUTTON_RESTART
	 */
	public void onRestart() {

	}

	/**
	 * Called when application crashed.
	 * 
	 * @param t
	 *            the thread that has an uncaught exception
	 * @param e
	 *            the exception that was thrown
	 */
	public void onCrashed(final Thread t, final Throwable e) {

	}

	@Override
	public void onSharedPreferenceChanged(
			final SharedPreferences sharedPreferences, final String key) {
		if (PREF_ENABLE_ACRA.equals(key)) {
			Boolean enableAcra = true;
			try {
				enableAcra = sharedPreferences.getBoolean(key,
						isCrashReportEnableByDefault());
			} catch (final Exception e) {
				// In case of a ClassCastException
			}
			if (enableAcra) {
				initAcra();
			} else {
				ErrorReporter.getInstance().disable();
			}
		}
	}

	public void setCrashReportEnable(final boolean enable) {
		final SharedPreferences prefs = getACRASharedPreferences();
		final Editor editor = prefs.edit();
		editor.putBoolean(PREF_ENABLE_ACRA, enable);
		editor.commit();
	}

	/**
	 * Override this method if you need to store "acra.disable" or "acra.enable"
	 * in a different SharedPrefence than the application's default.
	 * 
	 * @return The Shared Preferences where ACRA will check the value of the
	 *         setting which disables/enables it's action.
	 */
	public SharedPreferences getACRASharedPreferences() {
		return PreferenceManager.getDefaultSharedPreferences(this);
	}

	public boolean isCrashReportEnableByDefault() {
		return true;
	}

}
